package com.fort.teachermanagementsys.springsecurity.config;

import com.fort.teachermanagementsys.springsecurity.handler.*;
import com.fort.teachermanagementsys.springsecurity.jwtfilter.JWTAuthenticationTokenFilter;
import com.fort.teachermanagementsys.springsecurity.provider.UserAuthenticationProvider;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class WebSecurityConfig {

    private final UserAuthenticationEntryPointHandler authenticationEntryPointHandler;
    private final UserLoginSuccessHandler loginSuccessHandler;
    private final UserLoginFailureHandler loginFailureHandler;
    private final UserLogoutSuccessHandler logoutSuccessHandler;
    private final UserAuthAccessDeniedHandler accessDeniedHandler;
    private final UserAuthenticationProvider authenticationProvider;

    public WebSecurityConfig(UserAuthenticationEntryPointHandler authenticationEntryPointHandler,
                             UserLoginSuccessHandler loginSuccessHandler,
                             UserLoginFailureHandler loginFailureHandler,
                             UserLogoutSuccessHandler logoutSuccessHandler,
                             UserAuthAccessDeniedHandler accessDeniedHandler,
                             UserAuthenticationProvider authenticationProvider) {
        this.authenticationEntryPointHandler = authenticationEntryPointHandler;
        this.loginSuccessHandler = loginSuccessHandler;
        this.loginFailureHandler = loginFailureHandler;
        this.logoutSuccessHandler = logoutSuccessHandler;
        this.accessDeniedHandler = accessDeniedHandler;
        this.authenticationProvider = authenticationProvider;
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
        return configuration.getAuthenticationManager();
    }

    @Bean
    public JWTAuthenticationTokenFilter jwtAuthenticationTokenFilter(AuthenticationManager authenticationManager) {
        return new JWTAuthenticationTokenFilter(authenticationManager);
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http,
                                                   JWTAuthenticationTokenFilter jwtAuthenticationTokenFilter) throws Exception {
        http
                .csrf(AbstractHttpConfigurer::disable)
                .cors(AbstractHttpConfigurer::disable)
                .authorizeRequests(auth -> auth
                        .antMatchers(
                                "/user/login",
                                "/user/register",
                                "/swagger-ui/**",
                                "/v3/api-docs/**"
                        ).permitAll()
                        .anyRequest().authenticated()
                )
                .formLogin(form -> form
                        .loginProcessingUrl("/user/login")
                        .successHandler(loginSuccessHandler)
                        .failureHandler(loginFailureHandler)
                )
                .logout(logout -> logout
                        .logoutUrl("/user/logout")
                        .logoutSuccessHandler(logoutSuccessHandler)
                )
                .exceptionHandling(exception -> exception
                        .authenticationEntryPoint(authenticationEntryPointHandler)
                        .accessDeniedHandler(accessDeniedHandler)
                )
                .sessionManagement(session -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )
                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
                .authenticationProvider(authenticationProvider);

        return http.build();
    }
}
